package com.ckx.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ckx.constants.SystemConstants;
import com.ckx.domain.dto.MenuDto;
import com.ckx.domain.entity.RoleMenu;
import com.ckx.domain.vo.MenuByRoleAddVo;
import com.ckx.domain.vo.MenuVo;
import com.ckx.mapper.MenuMapper;
import com.ckx.service.MenuService;
import com.ckx.domain.entity.Menu;
import com.ckx.service.RoleMenuService;
import com.ckx.utils.BeanCopyUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.function.IntFunction;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author makejava
 * @since 2023-08-01 17:25:12
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private RoleMenuService roleMenuService;

    @Override
    public List<String> selectPermsByUserId(Long id) {
        //默认 id为 1 的是管理员
        if (SystemConstants.IS_ADMIN.equals(id)) {
            QueryWrapper<Menu> wrapper = new QueryWrapper<>();
            wrapper.lambda().in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            wrapper.lambda().eq(Menu::getStatus, SystemConstants.NORMAL);
            List<Menu> menus = this.list(wrapper);
            return menus.stream().map(menu -> menu.getPerms()).collect(Collectors.toList());
        }
        //非管理员
        List<String> perms = this.getBaseMapper().selectPermsByUserId(id);
        return perms;
    }

    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Long userId) {
        List<Menu> menus = null;
        //是管理员
        if (SystemConstants.IS_ADMIN.equals(userId)) {
            menus = this.getBaseMapper().selectAllRouterMenuTree(userId);
        } else {//非管理员
            menus = this.getBaseMapper().selectRouterMenuTreeByUserId(userId);
        }

        List<Menu> menuTree = buildMenuTree(menus, SystemConstants.PARENT);

        return menuTree;

    }

    @Override
    public List<MenuVo> selectAllMenus(String menuName, Integer status) {

        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(StringUtils.hasText(menuName), Menu::getMenuName, menuName);
        wrapper.lambda().eq(!Objects.isNull(status), Menu::getStatus, status);
        List<Menu> menus = this.getBaseMapper().selectList(wrapper);
        return menus.stream()
                .map(menu -> BeanCopyUtil.copyBean(menu, MenuVo.class))
                .collect(Collectors.toList());

    }

    @Override
    public void addMenu(MenuDto menuDto) {

        Menu menu = BeanCopyUtil.copyBean(menuDto, Menu.class);
        this.save(menu);

    }

    @Override
    public MenuVo getMenuInfo(Long id) {

        Menu menu = this.getById(id);
        return BeanCopyUtil.copyBean(menu, MenuVo.class);

    }

    @Override
    public void updateMenu(MenuDto menuDto) {
        Menu menu = BeanCopyUtil.copyBean(menuDto, Menu.class);
        this.getBaseMapper().updateById(menu);
    }

    @Override
    public void del4DelFlag(Long id) {
        UpdateWrapper<Menu> wrapper = new UpdateWrapper<>();
        wrapper.lambda().eq(Menu::getId, id);
        wrapper.lambda().set(Menu::getDelFlag, SystemConstants.DELFLAG);
        this.update(wrapper);
    }

    @Override
    public List<MenuByRoleAddVo> treeSelect() {
        List<Menu> menus = this.getBaseMapper().selectList(new QueryWrapper<>());
        return buildMenuTreeByRole(menus, SystemConstants.PARENT);
    }

    @Override
    public List<Long> roleMenuTreeSelect(Long id) {

        QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(RoleMenu::getRoleId, id);
        List<RoleMenu> roleMenus = roleMenuService.getBaseMapper().selectList(wrapper);
        return roleMenus.stream()
                .map(RoleMenu::getMenuId)
                .collect(Collectors.toList());
    }

    //封装成 MenuByRoleAddVo
    private List<MenuByRoleAddVo> buildMenuTreeByRole(@NotNull List<Menu> menus, Long parentId) {
        return menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> {
                    MenuByRoleAddVo vo = BeanCopyUtil.copyBean(menu, MenuByRoleAddVo.class).setLabel(menu.getMenuName());
                    return vo.setChildren(setChildren(menus, vo.getId()));
                })
                .collect(Collectors.toList());
    }
    //封装子节点
    private List<MenuByRoleAddVo> setChildren(@NotNull List<Menu> menus, Long parentId) {
        return menus.stream()
                .filter(menu -> {
                    return menu.getParentId().equals(parentId);
                })
                .map(menu -> {
                    MenuByRoleAddVo vo = BeanCopyUtil.copyBean(menu, MenuByRoleAddVo.class).setLabel(menu.getMenuName());
                    return vo.setChildren(setChildren(menus, vo.getId()));
                })
                .collect(Collectors.toList());
    }


    //得到父菜单
    private List<Menu> buildMenuTree(List<Menu> menus, Long parentId) {

        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))//找出父节点
                .map(menu -> menu.setChildren(getChildren(menus, menu.getId())))//找出子节点
                .collect(Collectors.toList());
        return menuTree;

    }

    //找出子菜单
    private List<Menu> getChildren(List<Menu> menus, Long parentId) {

        List<Menu> menuTree = menus.stream()
                .filter(m -> m.getParentId().equals(parentId))
                .map(m -> m.setChildren(getChildren(menus, m.getId())))//寻找子节点的子节点
                .collect(Collectors.toList());
        return menuTree;

    }
}

